package com.songcha.library_base.base

import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import android.view.*
import android.view.inputmethod.InputMethodManager
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.Fragment
import com.songcha.library_base.R
import com.songcha.library_base.config.SizeConfig
import com.songcha.library_common.handler.AppExitTipHandler
import com.songcha.library_common.ui.dialog.LoadingDialog
import com.songcha.library_common.ui.view.HeaderBarView

import com.songcha.library_common.util.ColorUtil
import com.songcha.library_common.util.KeyBoardUtil
import com.songcha.library_common.util.ScreenUtil
import com.songcha.library_common.util.StatusBarUtil
import me.jessyan.autosize.AutoSize
import me.jessyan.autosize.AutoSizeConfig

//activity perhaps use viewbinding or databinding
abstract class  BaseActivity: AppCompatActivity() , IBasePage, IOnInputUnFocus {
    private var mViewStubLoading:ViewStub?=null
    private var mViewLoading:View?=null

    private var mViewStubError:ViewStub?=null
    private var mViewError:View?=null

    private var mViewStubNoData:ViewStub?=null
    private var mViewNoData:View?=null

    private var mViewStubTimeout:ViewStub?=null
    private var mViewTimeout:View?=null

    private var mViewStubNoNetwork:ViewStub?=null
    private var mViewNoNetwork:View?=null

    private var mViewStubConnectError:ViewStub?=null
    private var mViewConnectError:View?=null

    private var mBtnRetry:Button?=null

    private var mLoadingDialog: LoadingDialog?=null

    protected var mRootView:View?=null

    //private var mIsApplyWindowInsetsCall=false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initOnCreate(savedInstanceState)
    }

    protected open fun initOnCreate(savedInstanceState: Bundle?){
        initStatusBar(savedInstanceState)
        initView(savedInstanceState)
        //setOnApplyWindowInsetsListener()
    }

    /*protected open fun setOnApplyWindowInsetsListener(){
        ViewCompat.setOnApplyWindowInsetsListener(window.decorView
        ) { v, insets ->
            //if(!mIsApplyWindowInsetsCall){
                onApplyWindowInsetsCall(v, insets)
                //mIsApplyWindowInsetsCall=true
            //}
            ViewCompat.onApplyWindowInsets(v, insets)
        }
    }*/

    override fun onApplyWindowInsetsCall(v: View, insets: WindowInsetsCompat){

    }

    private fun calculateLoadViewTopMargin():Int{
        var topMargin=getLoadViewTopMargin()
        if(isCalculateHearBarHeight()){
            topMargin+=HeaderBarView.DEFAULT_HEIGHT+StatusBarUtil.getStatusBarHeight(this)
        }
        return topMargin
    }

    protected open fun initLoad(rootView:View):View{
         if(!isNeedShowLoad()) return rootView
         val frameLayout=FrameLayout(this)
         val frameLayoutLp=ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)
         frameLayout.layoutParams=frameLayoutLp

         val vsLp=FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,FrameLayout.LayoutParams.MATCH_PARENT)
         vsLp.topMargin=calculateLoadViewTopMargin()

         mViewStubLoading=ViewStub(this)
         mViewStubLoading!!.layoutResource=getLoadingLayoutId()
         mViewStubLoading!!.layoutParams=vsLp

         mViewStubError=ViewStub(this)
         mViewStubError!!.layoutResource=getLoadErrorLayoutId()
         mViewStubError!!.layoutParams=vsLp

         mViewStubNoData=ViewStub(this)
         mViewStubNoData!!.layoutResource=getLoadNoDataLayoutId()
         mViewStubNoData!!.layoutParams=vsLp

         mViewStubTimeout=ViewStub(this)
         mViewStubTimeout!!.layoutResource=getLoadTimeoutLayoutId()
         mViewStubTimeout!!.layoutParams=vsLp

         mViewStubNoNetwork=ViewStub(this)
         mViewStubNoNetwork!!.layoutResource=getLoadNoNetworkLayoutId()
         mViewStubNoNetwork!!.layoutParams=vsLp

         mViewStubConnectError=ViewStub(this)
         mViewStubConnectError!!.layoutResource=getLoadConnectErrorLayoutId()
         mViewStubConnectError!!.layoutParams=vsLp

         frameLayout.addView(rootView)
         frameLayout.addView(mViewStubLoading)
         frameLayout.addView(mViewStubError)
         frameLayout.addView(mViewStubNoData)
         frameLayout.addView(mViewStubTimeout)
         frameLayout.addView(mViewStubNoNetwork)
         frameLayout.addView(mViewStubConnectError)

         return frameLayout
    }

    open fun isCalculateHearBarHeight():Boolean{
        return false
    }

    open fun getLoadViewTopMargin():Int{
        return 0
    }

    open fun getLoadingLayoutId():Int{
        return R.layout.base_stub_loading
    }

    override fun getLoadErrorLayoutId():Int{
        return R.layout.base_stub_error
    }

    override fun getLoadNoDataLayoutId():Int{
        return R.layout.base_stub_nodata
    }

    override fun getLoadTimeoutLayoutId():Int{
        return R.layout.base_stub_timeout
    }

    override fun getLoadNoNetworkLayoutId():Int{
        return R.layout.base_stub_no_network
    }

    override fun getLoadConnectErrorLayoutId():Int{
        return R.layout.base_stub_connect_error
    }

    override fun getLoadErrorTip(): String {
        return "加载失败"
    }

    override fun getLoadNoDataTip(): String {
        return "没有数据"
    }

    override fun getLoadTimeOutTip(): String {
        return "网络连接超时"
    }

    override fun getLoadNoNetworkTip(): String {
        return "请检查网络设置"
    }

    override fun getLoadConnectErrorTip(): String {
        return "网络连接失败"
    }

    protected open fun setLoadingDialogCancelable(cancelable:Boolean){
        mLoadingDialog?.setCancelable(cancelable)
    }

    protected open fun initStatusBar(savedInstanceState: Bundle?){
        //cause theme set full screen for splash,so need to clear flag in here
        window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
        StatusBarUtil.setTransparentStatusBar(this)
        StatusBarUtil.setStatusBarStyle(this,isDarkStatusBar())

        //perhaps use viewbinding or not,so need 2 method to set layout
        try{
            mRootView = getRootView() ?: LayoutInflater.from(this).inflate(getLayoutId(),null)

            mRootView?.post{
                onRootViewPost()
            }

            if(!isImmerseStatusBar()){
                val linear=LinearLayout(this)
                linear.orientation= LinearLayout.VERTICAL
                val statusBarView= View(this)
                statusBarView.setBackgroundColor(getStatusBarColor())
                linear.addView(statusBarView, LinearLayout.LayoutParams.MATCH_PARENT,StatusBarUtil.getStatusBarHeight(this))
                linear.addView(mRootView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
                val rootView=initLoad(linear)
                setContentView(rootView)
            }else{
                val rootView=initLoad(mRootView!!)
                setContentView(rootView)
            }

        }catch (e:Exception){
            e.printStackTrace()
        }

    }

    override fun onRootViewPost() {

    }

    //is need show load view
    override fun isNeedShowLoad():Boolean{
        return false
    }

    open fun getStatusBarColor():Int{
        return ColorUtil.getResourceColor(this, com.songcha.library_common.R.color.page_background)
    }

    open fun isDarkStatusBar():Boolean{
        return true
    }

    override fun initView(savedInstanceState: Bundle?){
        if(isNeedShowLoadingDialog()) mLoadingDialog= LoadingDialog(this)
    }

    override fun showLoadingDialog(cancelable: Boolean){
        mLoadingDialog?.let {
            if(!cancelable){
                it.setCancelable(false)
                it.setCanceledOnTouchOutside(false)
            }
            it.show()
        }

    }

    override fun hideLoadingDialog(){
        mLoadingDialog?.let {
            it.dismiss()
            it.setProgress(0)
        }
    }

    override fun setLoadingDialogProgress(progress: Int) {
        mLoadingDialog?.setProgress(progress)
    }

    //is need show loading dialog
    override fun isNeedShowLoadingDialog():Boolean{
        return false
    }

    override fun getRootView():View?{
        return null
    }

    override fun getLayoutId():Int{
        return 0
    }

    //autosize cannot detect the screen orientation change,so need to implement by self
    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        AutoSizeConfig.getInstance().screenWidth= ScreenUtil.getScreenWidth(this)
        AutoSizeConfig.getInstance().screenHeight=ScreenUtil.getScreenHeight(this)
        if(newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
            AutoSizeConfig.getInstance().isBaseOnWidth=false
            AutoSize.autoConvertDensityBaseOnHeight(this,SizeConfig.SCREEN_WIDTH_DP)
        }else{
            AutoSizeConfig.getInstance().isBaseOnWidth=true
            AutoSize.autoConvertDensityBaseOnWidth(this,SizeConfig.SCREEN_WIDTH_DP)
        }

    }

    //cancel focus and close keyboard when click input outsize
    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        if(ev==null) return super.dispatchTouchEvent(ev)
        if (ev.action == MotionEvent.ACTION_DOWN) {
            if (currentFocus!=null && currentFocus is EditText){//点击editText控件外部
                val editText=currentFocus as EditText
                val b=isShouldHideInput(editText , ev)
                if(b){
                    val imm =  getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                    if (imm != null) {
                        KeyBoardUtil.closeKeyboard(editText)
                        if (editText != null) {
                            editText.clearFocus()
                        }
                    }

                    onInputUnFocus()

                }

            }
        }
        return super.dispatchTouchEvent(ev)

    }

    override fun onInputUnFocus() {

    }

     private fun isShouldHideInput( editText: EditText, event:MotionEvent) :Boolean{
         val leftTop=intArrayOf(0,0)
         //get input current location
         editText.getLocationInWindow(leftTop)
         val left = leftTop[0]
         val top = leftTop[1]
         val bottom = top + editText.height
         val right = left +  editText.width
         return !(event.x > left && event.x < right
                 && event.y > top && event.y < bottom)

    }

    /***
     *  is immerse in statusbar
     */
     open fun isImmerseStatusBar():Boolean{
          return false
     }

     /*open fun getButtonRetryId():Int{
         return R.id.btn_retry
     }*/
    private fun initBtnRetry(view:View){
         mBtnRetry=view.findViewById(R.id.btn_retry)
         mBtnRetry?.let {
             if(showRetryBtn()){
                 it.setOnClickListener {
                     onRetry()
                 }
             }else{
                 it.visibility=View.GONE
             }
         }

    }

    protected open fun showRetryBtn():Boolean{
        return true
    }

    override fun getLoadBackgroundColor():Int{
        return ColorUtil.getResourceColor(this, com.songcha.library_common.R.color.page_background)
    }

    override fun onLoadErrorInflate(view: View) {

    }

    override fun onLoadNoDataInflate(view: View) {

    }

    override fun onLoadNoNetworkInflate(view: View) {

    }

    override fun onLoadTimeoutInflate(view: View) {

    }

    override fun onLoadConnectErrorInflate(view: View) {

    }

    override fun onLoadSuccess() {
        if(mViewLoading!=null)mViewLoading!!.visibility=View.GONE
        if(mViewError!=null)mViewError!!.visibility=View.GONE
        if(mViewNoData!=null)mViewNoData!!.visibility=View.GONE
        if(mViewTimeout!=null)mViewTimeout!!.visibility=View.GONE
        if(mViewNoNetwork!=null)mViewNoNetwork!!.visibility=View.GONE
    }

     override fun onLoading() {
         if(mViewStubLoading!=null){
             (mViewStubLoading!!.layoutParams as FrameLayout.LayoutParams).topMargin=calculateLoadViewTopMargin()
             if(mViewLoading==null){
                 mViewLoading=mViewStubLoading!!.inflate()
             }else{
                 mViewLoading!!.visibility=View.VISIBLE
             }
             mViewLoading!!.setBackgroundColor(getLoadBackgroundColor())
             if(mViewError!=null)mViewError!!.visibility=View.GONE
             if(mViewNoData!=null)mViewNoData!!.visibility=View.GONE
             if(mViewTimeout!=null)mViewTimeout!!.visibility=View.GONE
             if(mViewNoNetwork!=null)mViewNoNetwork!!.visibility=View.GONE
             if(mViewConnectError!=null)mViewConnectError!!.visibility=View.GONE
         }

     }

    override fun onLoadError(e: Throwable) {
        if(mViewStubError!=null){
            (mViewStubError!!.layoutParams as FrameLayout.LayoutParams).topMargin=calculateLoadViewTopMargin()
            if(mViewError==null){
                mViewError=mViewStubError!!.inflate()
                mViewError!!.findViewById<TextView>(R.id.tv_msg).text=getLoadErrorTip()
                onLoadErrorInflate(mViewError!!)
            }else{
                mViewError!!.visibility=View.VISIBLE
            }
            mViewError!!.setBackgroundColor(getLoadBackgroundColor())
            if(mViewLoading!=null)mViewLoading!!.visibility=View.GONE
            if(mViewNoData!=null)mViewNoData!!.visibility=View.GONE
            if(mViewTimeout!=null)mViewTimeout!!.visibility=View.GONE
            if(mViewNoNetwork!=null)mViewNoNetwork!!.visibility=View.GONE
            if(mViewConnectError!=null)mViewConnectError!!.visibility=View.GONE

            initBtnRetry(mViewError!!)
        }
    }

    override fun onLoadNoNetwork() {
        if(mViewStubNoNetwork!=null){
            (mViewStubNoNetwork!!.layoutParams as FrameLayout.LayoutParams).topMargin=calculateLoadViewTopMargin()
            if(mViewNoNetwork==null){
                mViewNoNetwork=mViewStubNoNetwork!!.inflate()
                mViewNoNetwork!!.findViewById<TextView>(R.id.tv_msg).text=getLoadNoNetworkTip()
                onLoadNoNetworkInflate(mViewNoNetwork!!)
            }else{
                mViewNoNetwork!!.visibility=View.VISIBLE
            }
            mViewNoNetwork!!.setBackgroundColor(getLoadBackgroundColor())
            if(mViewLoading!=null)mViewLoading!!.visibility=View.GONE
            if(mViewNoData!=null)mViewNoData!!.visibility=View.GONE
            if(mViewTimeout!=null)mViewTimeout!!.visibility=View.GONE
            if(mViewError!=null)mViewError!!.visibility=View.GONE
            if(mViewConnectError!=null)mViewConnectError!!.visibility=View.GONE

            initBtnRetry(mViewNoNetwork!!)
        }
    }

    override fun onLoadConnectError() {
        if(mViewStubConnectError!=null){
            (mViewStubConnectError!!.layoutParams as FrameLayout.LayoutParams).topMargin=calculateLoadViewTopMargin()
            if(mViewConnectError==null){
                mViewConnectError=mViewStubConnectError!!.inflate()
                mViewConnectError!!.findViewById<TextView>(R.id.tv_msg).text=getLoadConnectErrorTip()
                onLoadConnectErrorInflate(mViewConnectError!!)
            }else{
                mViewConnectError!!.visibility=View.VISIBLE
            }
            mViewConnectError!!.setBackgroundColor(getLoadBackgroundColor())
            if(mViewLoading!=null)mViewLoading!!.visibility=View.GONE
            if(mViewNoData!=null)mViewNoData!!.visibility=View.GONE
            if(mViewTimeout!=null)mViewTimeout!!.visibility=View.GONE
            if(mViewError!=null)mViewError!!.visibility=View.GONE
            if(mViewNoNetwork!=null)mViewNoNetwork!!.visibility=View.GONE

            initBtnRetry(mViewConnectError!!)
        }
    }

    override fun onLoadTimeOut() {
        if(mViewStubTimeout!=null){
            (mViewStubTimeout!!.layoutParams as FrameLayout.LayoutParams).topMargin=calculateLoadViewTopMargin()
            if(mViewTimeout==null){
                mViewTimeout=mViewStubTimeout!!.inflate()
                mViewTimeout!!.findViewById<TextView>(R.id.tv_msg).text=getLoadTimeOutTip()
                onLoadTimeoutInflate(mViewTimeout!!)
            }else{
                mViewTimeout!!.visibility=View.VISIBLE
            }
            mViewTimeout!!.setBackgroundColor(getLoadBackgroundColor())
            if(mViewLoading!=null)mViewLoading!!.visibility=View.GONE
            if(mViewNoData!=null)mViewNoData!!.visibility=View.GONE
            if(mViewNoNetwork!=null)mViewNoNetwork!!.visibility=View.GONE
            if(mViewError!=null)mViewError!!.visibility=View.GONE
            if(mViewConnectError!=null)mViewConnectError!!.visibility=View.GONE

            initBtnRetry(mViewTimeout!!)
        }
    }

    override fun onLoadNoData() {
        if(mViewStubNoData!=null){
            (mViewStubNoData!!.layoutParams as FrameLayout.LayoutParams).topMargin=calculateLoadViewTopMargin()
            if(mViewNoData==null){
                mViewNoData=mViewStubNoData!!.inflate()
                mViewNoData!!.findViewById<TextView>(R.id.tv_msg).text=getLoadNoDataTip()
                onLoadNoDataInflate(mViewNoData!!)
            }else{
                mViewNoData!!.visibility=View.VISIBLE
            }
            mViewNoData!!.setBackgroundColor(getLoadBackgroundColor())
            if(mViewLoading!=null)mViewLoading!!.visibility=View.GONE
            if(mViewTimeout!=null)mViewTimeout!!.visibility=View.GONE
            if(mViewNoNetwork!=null)mViewNoNetwork!!.visibility=View.GONE
            if(mViewError!=null)mViewError!!.visibility=View.GONE
            if(mViewConnectError!=null)mViewConnectError!!.visibility=View.GONE

            initBtnRetry(mViewNoData!!)
        }
    }

    protected open fun onRetry() {
        //onLoading()
    }

    override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            return onKeyBack(keyCode,event)
        }
        return super.onKeyUp(keyCode, event)
    }

    protected open fun onKeyBack(keyCode: Int, event: KeyEvent?):Boolean{
        return super.onKeyUp(keyCode, event)
    }

   override fun isBaseOnWidth(): Boolean {
        return true
    }

    override fun getSizeInDp(): Float {
        return SizeConfig.SCREEN_WIDTH_DP
    }

}